<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
    <video id="video" width="100%" height="100%" autoplay="autoplay" ></video>
<!--    <canvas id="canvas" width="500px" height="500px"></canvas>-->
<!--    <br>-->
    <img src="your-image-file.jpg" alt="Overlay Image" class="overlay-image">
    <input type="button" title="HTML5摄像头" value="开启摄像头" onclick="getMedia()"/>
    <script>
        // 初始化WebSocket连接
        window.ws = new WebSocket('ws://116.205.98.151:8080/websocket');
        // 连接打开
        window.ws.onopen = function() {
            console.log('WebSocket connection established');
        };
        //接收消息
        window.ws.onmessage = function(event) {
            const message = JSON.parse(event.data);
            if (message.type === 'answer') {
                peerConnection.setRemoteDescription(new RTCSessionDescription(message.data));
            }
            // 处理其他类型的信令消息
        };
        // 连接关闭
        window.ws.onclose = function() {
            console.log('WebSocket connection closed');
        };
        // 错误事件
        window.ws.onerror = function(error) {
            console.error('WebSocket error:', error);
        };

        let peerConnection;

        // 用于获取用户的媒体流（视频和音频）
        function getMedia() {
            let constraints = {
                video: {
                    width: { ideal: 1400 },
                    height: { ideal: 720 },
<!--                    // 后置摄像头-->
<!--                    facingMode: {-->
<!--                        exact: 'environment'-->
<!--                      }-->
                },
                audio: true // 是否需要音频流
            };

            let video = document.getElementById("video"); // 获取页面上的 <video> 元素
            let promise = navigator.mediaDevices.getUserMedia(constraints); // 请求获取媒体流，promise储存成功和失败两种情况
            /*
            MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可，媒体输入会产生一个MediaStream，里面包含了请求的媒体类型的轨道。
            此流可以包含一个视频轨道（来自硬件或者虚拟视频源，比如相机、视频采集设备和屏幕共享服务等等）、一个音频轨道（同样来自硬件或虚拟音频源，比如麦克风、A/D 转换器等等），也可能是其他轨道类型
            传入约束：constraints
            它返回一个 Promise 对象，成功后会resolve回调一个 MediaStream 对象。
            若用户拒绝了使用权限，或者需要的媒体源不可用，promise会reject回调一个 PermissionDeniedError 或者 NotFoundError
            */

            promise.then(function (MediaStream) {
                video.srcObject = MediaStream;
                video.play();

                // 创建RTCPeerConnection实例
                peerConnection = new RTCPeerConnection({
                    iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] // 使用公共STUN服务器
                });

                // 添加stream到peerConnection
                MediaStream.getTracks().forEach(track => {
                    peerConnection.addTrack(track, MediaStream);
                });

                // 创建offer
                peerConnection.createOffer().then(offer => {
                    peerConnection.setLocalDescription(new RTCSessionDescription(offer));
                    // 发送offer到后端
                    sendOfferToBackend(offer);
                });

                // 监听ICE候选事件
                peerConnection.onicecandidate = event  => {
                    if (event.candidate) {
                        // 发送candidate到后端
                        sendCandidateToBackend(event.candidate);
                    }
                };
            }).catch(error => {
                console.error('Error accessing media devices.', error);
            });
        }

        // 用于通过WebSocket将SDP offer发送到后端
        function sendOfferToBackend(offer) {
            // 实现发送逻辑，通过WebSocket
            console.log('Sending offer to backend:', offer);
            // 假设有一个WebSocket连接
            if (window.ws) {
                window.ws.send(JSON.stringify({ type: 'offer', data: offer }));
            }
        }
        // 用于通过WebSocket将ICE candidate发送到后端
        function sendCandidateToBackend(candidate) {
            // 实现发送逻辑，例如通过WebSocket或HTTP
            console.log('Sending candidate to backend:', candidate);
            // 假设有一个WebSocket连接
            if (window.ws) {
                window.ws.send(JSON.stringify({ type: 'candidate', data: candidate }));
            }
        }

        // 处理从后端接收的answer监听window.onmessage事件，用于接收从后端发送的answer，并将其设置为远程描述
        /*
            message.type 表示消息的类型。在WebRTC的信令过程中，有几种类型的消息，包括offer、answer和candidate。
            'answer' 是一种特定类型的消息，它包含了对先前收到的offer的响应。这个响应包含了远程对等端的媒体信息和连接参数。
            peerConnection.setRemoteDescription() 是一个方法，它用于设置远程对等端的会话描述。这是建立连接过程中的关键步骤，它告诉本地 RTCPeerConnection 实例如何与远程对等端通信。
            new RTCSessionDescription(message.data) 创建一个新的 RTCSessionDescription 对象，该对象包含从后端接收到的answer信息。
            通过调用 setRemoteDescription() 方法并传入这个新创建的 RTCSessionDescription 对象，前端的 RTCPeerConnection 实例被配置为知道如何与远程对等端进行通信。
        */
        window.onmessage = event => {
            const message = JSON.parse(event.data);
            if (message.type === 'answer') {
                peerConnection.setRemoteDescription(new RTCSessionDescription(message.data));
            }
        };

    </script>
</body>
</html>